package weapon

import (
    "cloud_worm/wormweb/controllers/ctrconfig"
    "cloud_worm/wormweb/controllers/ctrutil"
    "cloud_worm/util/uid"
    "time"
    "github.com/astaxie/beego/logs"
    "cloud_worm/util/uhttp"
    "strings"
    "cloud_worm/util/uconst"
    "fmt"
    "path/filepath"
    "os"
    "io/ioutil"
    "cloud_worm/util/umodels/mysqldb"
    "cloud_worm/util/umodels/mysqldb/dbmanager"
    "cloud_worm/util/umodels/mysqldb/dbtask"
    "cloud_worm/util/umodels/mysqldb/dbdata"
    "cloud_worm/wormweb/controllers/ctrsecurity/webtask/fasttask"
    "cloud_worm/wormweb/controllers/ctrinner/taskqueue"
)

type TaskController struct {
    ctrconfig.LoginCtr
}

// oneAccessSrvTask 针对一个access server创建任务
func (t *TaskController) oneAccessSrvTask(taskWps []string, comment string) error {
    addr := t.GetString("access_srv", mysqldb.SelectStrAll)
    if addr == mysqldb.SelectStrAll {
        t.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeParamErr, "no input access_srv address", nil)
        t.ServeJSON()
        return fmt.Errorf("no input access server address")
    }

    wid := dbmanager.WormId{}
    accessList, err := wid.SelectAccessSrvList(mysqldb.StatusAll)
    if err != nil {
        t.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeSystemErr, "select access_srv address error", nil)
        t.ServeJSON()
        return fmt.Errorf("select access server address error: %s", err.Error())
    }
    isMatch := false
    for _, access := range accessList {
        if access.ServerAddr == addr {
            isMatch = true
            break
        }
    }
    if isMatch == false {
        t.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeParamErr, "input access_srv address no have", nil)
        t.ServeJSON()
        return fmt.Errorf("input access server address no have: %s", addr)
    }

    // 查找机器数 TODO: run mode的入参
    machineSize, err := wid.Count(dbmanager.AgentOnline, mysqldb.SelectIntAll, mysqldb.SelectStrAll,
        mysqldb.SelectStrAll, mysqldb.SelectStrAll, addr, mysqldb.SelectIntAll, mysqldb.SelectIntAll, "xxx")
    if err != nil {
        t.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeParamErr, "input access address for select error.", nil)
        t.ServeJSON()
        return fmt.Errorf("the input serveradd(%s) for select error: %s", addr, err.Error())
    }

    // 准备插入insert
    task := &dbtask.WeaponTask{
        TaskId:      uid.TaskIdProducer().CreateTaskId(),
        TaskOwner:   t.UserInfo.Username,
        TargetType:  ctrutil.TaskForAccessSrv,
        Target:      addr,
        WeaponsName: strings.Join(taskWps, ","),
        Comment:     comment,
        SumCount:    int(machineSize) * len(taskWps),
        Created:     time.Now().Unix(),
        Status:      ctrutil.WEAPON_TASK_NO_DO,
    }
    task.Updated = task.Created

    err = task.Insert()
    if err != nil {
        t.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeSystemErr, "insert task error.", nil)
        t.ServeJSON()
        return fmt.Errorf("insert task error: %s", err.Error())
    }

    return nil
}

/**
 @Description：处理输入apply_name为具体应用名的操作
 @Param:
 @Return：
    error           发生错误，并回复http request
    nil             成功，未回复
 */
func (t *TaskController) oneApplyMachineTask(targetName string, taskWps []string, comment string) error {

    // 匹配application
    application := &dbmanager.Application{Name: targetName}
    err := application.Read("name")
    if err != nil {
        t.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeParamErr,"input application name.", nil)
        t.ServeJSON()
        return fmt.Errorf("input application name error: %s", err.Error())
    }

    // 准备主机host
    mach := &dbmanager.Machine{ApplyId: application.Id}
    machineSize, err := mach.Count(mysqldb.StatusValid, application.Id, mysqldb.SelectStrAll, mysqldb.SelectStrAll)
    if err != nil {
        t.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeParamErr, "input apply name for select error.", nil)
        t.ServeJSON()
        return fmt.Errorf("the input apply name for select error: %s", err.Error())
    }

    // 准备插入insert
    task := &dbtask.WeaponTask{
        TaskId:      uid.TaskIdProducer().CreateTaskId(),
        TaskOwner:   t.UserInfo.Username,
        TargetType:  ctrutil.TaskForApplication,
        Target:      application.Name,
        WeaponsName: strings.Join(taskWps, ","),
        Comment:     comment,
        SumCount:    int(machineSize) * len(taskWps),
        Created:     time.Now().Unix(),
        Status:      ctrutil.WEAPON_TASK_NO_DO,
    }
    task.Updated = task.Created

    err = task.Insert()
    if err != nil {
        t.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeSystemErr, "insert task error.", nil)
        t.ServeJSON()
        return fmt.Errorf("insert task error: %s", err.Error())
    }

    return nil
}

/**
 @Description：基于ip list的方式创建任务
 @Param:
 @Return：
 */
func (t *TaskController) ipListTask(taskWps []string, comment string) error {
    // weapon分析
    ipsStr := t.GetString("ips", mysqldb.SelectStrAll)                   // 涉及的ip，采用","号分割
    if ipsStr == mysqldb.SelectStrAll {
        t.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeParamErr, "no input any ips", nil)
        t.ServeJSON()
        return fmt.Errorf("no input any ips")
    }
    var ips []string
    for _, item := range strings.Split(strings.TrimSpace(ipsStr), ",") {
        item = strings.TrimSpace(item)
        if item != "" {
            ips = append(ips, item)
        }
    }
    if len(ips) == 0 {
        t.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeParamErr, "no input any ips", nil)
        t.ServeJSON()
        return fmt.Errorf("no input any ips")
    }

    // 准备任务
    wormId := dbmanager.WormId{}
    onlineCnt, err := wormId.CountByIPs(mysqldb.SelectOffsetZero, mysqldb.SelectLimitAll,
        dbmanager.AgentOnline, mysqldb.SelectIntAll, ips, ctrutil.RunMode)
    if err != nil {
        t.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeSystemErr, "select online count failed.", nil)
        t.ServeJSON()
        return fmt.Errorf("select online count failed: %s", err.Error())
    }
    // 将ips保存到临时文件中
    taskID := uid.TaskIdProducer().CreateTaskId()      // 先计算得到task id
    ipsFileName := filepath.Join(ctrutil.TmpDir, taskID) // 利用task id作为ip list file
    fp, err := os.OpenFile(ipsFileName, os.O_WRONLY | os.O_TRUNC | os.O_CREATE, 0644)
    if err != nil {
        t.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeSystemErr, "create ips file failed.", nil)
        t.ServeJSON()
        return fmt.Errorf("create ips file failed: %s", err.Error())
    }
    defer fp.Close()
    _, err = fp.WriteString(strings.Join(ips, ","))
    if err != nil {
        t.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeSystemErr, "write ips file failed.", nil)
        t.ServeJSON()
        return fmt.Errorf("write ips file failed: %s", err.Error())
    }

    // 准备插入insert
    task := &dbtask.WeaponTask{
        TaskId:      taskID,
        TaskOwner:   t.UserInfo.Username,
        TargetType:  ctrutil.TaskForIPList,
        Target:      ipsFileName,
        WeaponsName: strings.Join(taskWps, ","),
        Comment:     comment,
        SumCount:    int(onlineCnt) * len(taskWps),
        Created:     time.Now().Unix(),
        Status:      ctrutil.WEAPON_TASK_NO_DO,
    }
    task.Updated = task.Created

    err = task.Insert()
    if err != nil {
        t.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeSystemErr, "insert task error.", nil)
        t.ServeJSON()
        return fmt.Errorf("insert task error: %s", err.Error())
    }

    return nil
}

/**
 @Description：处理输入apply_name为all的情况，表示所有机器
 @Param:
 @Return：
 */
func (t *TaskController) allMachineTask(taskWps []string, comment string) error {

    wormId := dbmanager.WormId{}
    onlineCount, err := wormId.CountStatus(dbmanager.AgentOnline, ctrutil.RunMode)
    if err != nil {
        t.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeSystemErr, "select online count failed.", nil)
        t.ServeJSON()
        return fmt.Errorf("select online count failed: %s", err.Error())
    }

    // 准备插入insert
    task := &dbtask.WeaponTask{
        TaskId:      uid.TaskIdProducer().CreateTaskId(),
        TaskOwner:   t.UserInfo.Username,
        TargetType:  ctrutil.TaskForAll,
        Target:      ctrutil.TaskAllApplication,
        WeaponsName: strings.Join(taskWps, ","),
        Comment:     comment,
        SumCount:    int(onlineCount) * len(taskWps),
        Created:     time.Now().Unix(),
        Status:      ctrutil.WEAPON_TASK_NO_DO,
    }
    task.Updated = task.Created

    err = task.Insert()
    if err != nil {
        t.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeSystemErr, "insert task error.", nil)
        t.ServeJSON()
        return fmt.Errorf("insert task error: %s", err.Error())
    }

    return nil
}

/**
 创建任务
 任务执行的范围：
    1. 指定应用为单位；
    2. 指定全局
 */
func (t *TaskController) CreateTask() {
    t.Manager()

    type InputInfo struct {
        Comment         string      `json:"comment"`
        ApplyName       string      `json:"apply_name"`
        Weapons         string      `json:"weapons"`                // 涉及的weapon，采用","号分割，weapon name
    }
    var input InputInfo
    if err := t.Unmarshal(&input); err != nil {
        t.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeReqBodyErr, err.Error(), nil)
        t.ServeJSON()
        return
    }

    if input.ApplyName == mysqldb.SelectStrAll {
        logs.Warn("input apply name error.")
        t.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeParamErr, "input apply name error.", nil)
        t.ServeJSON()
        return
    }

    if input.Weapons == mysqldb.SelectStrAll {
        logs.Warning("no input any weapon.")
        t.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeParamErr, "no input any weapon", nil)
        t.ServeJSON()
        return
    }
    var taskWp []string
    for _, item := range strings.Split(strings.TrimSpace(input.Weapons), ",") {
        item = strings.TrimSpace(item)
        if item != "" {
            taskWp = append(taskWp, item)
        }
    }
    if len(taskWp) == 0 {
        logs.Warning("no input any weapon.")
        t.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeParamErr, "no input any weapon", nil)
        t.ServeJSON()
        return
    }

    // 任务创建
    if input.ApplyName == ctrutil.TaskAllApplication {
        // 所有机器
        err := t.allMachineTask(taskWp, input.Comment)
        if err != nil {
            // 异常已经回复
            logs.Error(err.Error())
            return
        }
    } else if input.ApplyName == ctrutil.TaskSomeIPList {
        // 指定ip list
        err := t.ipListTask(taskWp, input.Comment)
        if err != nil {
            logs.Error(err.Error())
            return
        }
    } else if input.ApplyName == ctrutil.TaskOneWolServer {
        // 指定一个access server下的扫描
        err := t.oneAccessSrvTask(taskWp, input.Comment)
        if err != nil {
            logs.Error(err.Error())
            return
        }
    } else {
        // 执行应用
        err := t.oneApplyMachineTask(input.ApplyName, taskWp, input.Comment)
        if err != nil {
            // 异常已经回复
            logs.Error(err.Error())
            return
        }
    }

    t.Data["json"] = uhttp.CreateOkResponse(nil)
    t.ServeJSON()
    return
}

/**
 执行任务
 */
func (t *TaskController) ExecTask()  {
    t.Manager()

    type InputInfo struct {
        TaskId          string      `json:"task_id"`
    }
    var input InputInfo
    if err := t.Unmarshal(&input); err != nil {
        t.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeReqBodyErr, err.Error(), nil)
        t.ServeJSON()
        return
    }

    if len(input.TaskId) != uconst.TaskIdLen {
        logs.Warning("exec task input task id error.")
        t.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeParamErr, "exec task input task id error.", nil)
        t.ServeJSON()
        return
    }

    // 读取task
    task := &dbtask.WeaponTask{TaskId: input.TaskId}
    err := task.Read("task_id")
    if err != nil {
        logs.Warning("exec task no record by task id: %s, error: %s", input.TaskId, err.Error())
        t.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeParamErr, fmt.Sprintf("exec task no record by task id: %s", input.TaskId), nil)
        t.ServeJSON()
        return
    }
    if task.TargetType != ctrutil.TaskForApplication && task.TargetType != ctrutil.TaskForMachine &&
        task.TargetType != ctrutil.TaskForAll && task.TargetType != ctrutil.TaskForIPList &&
            task.TargetType != ctrutil.TaskForAccessSrv { // 保证task type是application的
        logs.Error(fmt.Sprintf("task(%s) not for application or machine or all.", input.TaskId))
        t.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeSystemErr, "task not for application or machine or all.", nil)
        t.ServeJSON()
        return
    }

    // 更新task
    task.Updated = time.Now().Unix()
    task.Status = ctrutil.WEAPON_TASK_DOING
    err = task.Update("updated", "status")
    if err != nil {
        logs.Error(fmt.Sprintf("update task(%s) status failed: %s", input.TaskId, err.Error()))
        t.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeSystemErr, "update task status failed.", nil)
        t.ServeJSON()
        return
    }

    // 准备下发任务的数据
    if task.TargetType == ctrutil.TaskForMachine {
        err = t.sendTaskItemForMachine(task)
        if err != nil {
            t.updateTaskFailed(task)
            return
        }
    } else if task.TargetType == ctrutil.TaskForApplication {
        err = t.sendTaskItemForApplication(task)
        if err != nil {
            t.updateTaskFailed(task)
            return
        }
    } else if task.TargetType == ctrutil.TaskForAll {
        // 全量all machine
        err = t.sendTaskItemForAll(task)
        if err != nil {
            t.updateTaskFailed(task)
            return
        }
    } else if task.TargetType == ctrutil.TaskForIPList {
        err = t.sendTaskItemForIPList(task)
        if err != nil {
            t.updateTaskFailed(task)
            return
        }
    } else if task.TargetType == ctrutil.TaskForAccessSrv {
        err = t.sendTaskItemForAccessSrv(task)
        if err != nil {
            t.updateTaskFailed(task)
            return
        }
    }

    t.Data["json"] = uhttp.CreateOkResponse(nil)
    t.ServeJSON()
    return
}

// sendTaskItemForAccessSrv 下发针对access server的任务
func (t *TaskController) sendTaskItemForAccessSrv(task *dbtask.WeaponTask) error {
    worm := dbmanager.WormId{}
    wormIds, err := worm.Select(mysqldb.SelectOffsetZero, mysqldb.SelectLimitAll, dbmanager.AgentOnline,
        mysqldb.SelectIntAll, mysqldb.SelectStrAll, mysqldb.SelectStrAll, mysqldb.SelectStrAll,
            task.Target, mysqldb.SelectIntAll, mysqldb.SelectIntAll, ctrutil.RunMode)
    if err != nil {
        logs.Error(fmt.Sprintf("get '%s' online agent failed: %s", task.Target, err.Error()))
        t.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeSystemErr, "get all online agent failed.", nil)
        t.ServeJSON()
        return fmt.Errorf("get '%s' online agent failed", task.Target)
    }

    // weapon
    wpsName := strings.Split(task.WeaponsName, ",")

    sumItem := len(wormIds) * len(wpsName)
    notifyChan := fasttask.WaitTaskFinish(task, sumItem, fasttask.IsNeedTaskAlertDeal(task.WeaponsName))

    for _, m := range wormIds {
        for _, wp := range wpsName {
            taskItem := &fasttask.TaskItem{
                NotifyChan: notifyChan,
                TaskId: task.TaskId,
                WormId: m.AgentId,
                WeaponName: wp,
                Input: "",                              // todo：考虑何时可以设置入参的设计
            }
            //logs.Info(fmt.Sprintf("%s, %s, task: %s", taskItem.WeaponName, taskItem.AgentId, taskItem.TaskId))
            taskqueue.FastQueInst().MsgQ.Push(taskItem)
        }
    }

    return nil
}

/**
 @Description：task失败的update
 @Param:
 @Return：
 */
func (t *TaskController) updateTaskFailed(task *dbtask.WeaponTask) {
    task.Updated = time.Now().Unix()
    task.Status = ctrutil.WEAPON_TASK_DO_FAILED
    err := task.Update("updated", "status")
    if err != nil {
        logs.Error(fmt.Sprintf("update task(%s) status failed: %s", task.TaskId, err.Error()))
    }
    return
}

/**
 @Description：下发ip list的任务
 @Param:
 @Return：
    nil         成功
    error       失败，http response完成
 */
func (t *TaskController) sendTaskItemForIPList(task *dbtask.WeaponTask) error {
    data, err := ioutil.ReadFile(task.Target)
    if err != nil {
        logs.Error(fmt.Sprintf("read '%s' failed: %s", task.Target, err.Error()))
        t.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeSystemErr, fmt.Sprintf("read '%s' failed", task.Target), nil)
        t.ServeJSON()
        return fmt.Errorf("read '%s' failed: %s", task.Target, err.Error())
    }
    ips := strings.Split(string(data), ",")
    os.Remove(task.Target)

    wormId := dbmanager.WormId{}
    wormIDs, err := wormId.SelectByIPs(mysqldb.SelectOffsetZero, mysqldb.SelectLimitAll, dbmanager.AgentOnline, mysqldb.SelectIntAll, ips, ctrutil.RunMode)
    if err != nil {
        t.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeSystemErr, "select online agent failed.", nil)
        t.ServeJSON()
        return fmt.Errorf("select online agent failed: %s", err.Error())
    }

    // weapon
    wpsName := strings.Split(task.WeaponsName, ",")

    sumItem := len(wormIDs) * len(wpsName)
    notifyChan := fasttask.WaitTaskFinish(task, sumItem, fasttask.IsNeedTaskAlertDeal(task.WeaponsName))

    for _, m := range wormIDs {
        for _, wp := range wpsName {
            taskItem := &fasttask.TaskItem{
                NotifyChan: notifyChan,
                TaskId: task.TaskId,
                WormId: m.AgentId,
                WeaponName: wp,
                Input: "",                              // todo：考虑何时可以设置入参的设计
            }
            //logs.Info(fmt.Sprintf("%s, %s, task: %s", taskItem.WeaponName, taskItem.AgentId, taskItem.TaskId))
            taskqueue.FastQueInst().MsgQ.Push(taskItem)
        }
    }

    return nil
}

/**
 @Description：下发针对application的任务
 @Param:
 @Return：
    nil         成功
    error       失败，http response完成
 */
func (t *TaskController) sendTaskItemForAll(task *dbtask.WeaponTask) error {

    wormId := dbmanager.WormId{}
    wormIds, err := wormId.SelectStatus(mysqldb.SelectOffsetZero, mysqldb.SelectLimitAll, dbmanager.AgentOnline, ctrutil.RunMode)
    if err != nil {
        logs.Error(fmt.Sprintf("get all online agent failed: %s", err.Error()))
        t.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeSystemErr, "get all online agent failed.", nil)
        t.ServeJSON()
        return fmt.Errorf("get all online agent failed")
    }

    // weapon
    wpsName := strings.Split(task.WeaponsName, ",")

    sumItem := len(wormIds) * len(wpsName)
    notifyChan := fasttask.WaitTaskFinish(task, sumItem, fasttask.IsNeedTaskAlertDeal(task.WeaponsName))

    for _, m := range wormIds {
        for _, wp := range wpsName {
            taskItem := &fasttask.TaskItem{
                NotifyChan: notifyChan,
                TaskId: task.TaskId,
                WormId: m.AgentId,
                WeaponName: wp,
                Input: "",                              // todo：考虑何时可以设置入参的设计
            }
            //logs.Info(fmt.Sprintf("%s, %s, task: %s", taskItem.WeaponName, taskItem.WormId, taskItem.TaskId))
            taskqueue.FastQueInst().MsgQ.Push(taskItem)
        }
    }

    return nil
}

/**
 @Description：下发针对application的任务
 @Param:
 @Return：
    nil         成功
    error       失败，http response完成
 */
func (t *TaskController) sendTaskItemForApplication(task *dbtask.WeaponTask) error {
    application := &dbmanager.Application{Name: task.Target}
    err := application.Read("name")
    if err != nil {
        logs.Error(fmt.Sprintf("task(%s) application target read error: %s", task.TaskId, err.Error()))
        t.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeSystemErr, "task application target error.", nil)
        t.ServeJSON()
        return fmt.Errorf("task application target read error")
    }
    ma := &dbmanager.Machine{ApplyId: application.Id}
    machines, err := ma.Select(mysqldb.SelectOffsetZero, mysqldb.SelectLimitAll,
        mysqldb.StatusValid, int64(application.Id), mysqldb.SelectStrAll, mysqldb.SelectStrAll)
    if err != nil {
        task.Status = ctrutil.WEAPON_TASK_DO_FAILED
        task.Updated = time.Now().Unix()
        task.Update("updated", "status")
        logs.Error(fmt.Sprintf("select machines for application(%s) failed: %s", application.Name, err.Error()))
        t.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeSystemErr, "select machines error.", nil)
        t.ServeJSON()
        return fmt.Errorf("select machines for application failed")
    }
    // weapon
    wpsName := strings.Split(task.WeaponsName, ",")

    sumItem := len(machines) * len(wpsName)
    notifyChan := fasttask.WaitTaskFinish(task, sumItem, fasttask.IsNeedTaskAlertDeal(task.WeaponsName))

    for _, m := range machines {
        for _, wp := range wpsName {
            taskItem := &fasttask.TaskItem{
                NotifyChan: notifyChan,
                TaskId: task.TaskId,
                WormId: m.WormId,
                WeaponName: wp,
                Input: "",                              // todo：考虑何时可以设置入参的设计
            }
            taskqueue.FastQueInst().MsgQ.Push(taskItem)
        }
    }

    return nil
}

/**
 @Description：下发针对machine的任务
 @Param:
 @Return：
     nil         成功
     error       失败，http response完成
 */
func (t *TaskController) sendTaskItemForMachine(task *dbtask.WeaponTask) error {
    machine := &dbmanager.Machine{Ip: task.Target, Status: mysqldb.StatusValid}
    err := machine.Read("ip", "status")
    if err != nil {
        task.Status = ctrutil.WEAPON_TASK_DO_FAILED
        task.Updated = time.Now().Unix()
        task.Update("updated", "status")
        logs.Error(fmt.Sprintf("select machines for ip(%s) failed: %s", task.Target, err.Error()))
        t.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeSystemErr, "select machines error.", nil)
        t.ServeJSON()
        return fmt.Errorf("select machines for ip failed")
    }
    // weapon
    wpsName := strings.Split(task.WeaponsName, ",")

    sumItem := len(wpsName)
    notifyChan := fasttask.WaitTaskFinish(task, sumItem, fasttask.IsNeedTaskAlertDeal(task.WeaponsName))

    for _, wp := range wpsName {
        taskItem := &fasttask.TaskItem{
            NotifyChan: notifyChan,
            TaskId: task.TaskId,
            WormId: machine.WormId,
            WeaponName: wp,
            Input: "",                              // todo：考虑何时可以设置入参的设计
        }
        taskqueue.FastQueInst().MsgQ.Push(taskItem)
    }

    return nil
}

/**
 展示任务
 */
func (t *TaskController) List()  {
    t.Manager()

    offset, limit := t.DealPage()

    status, err := t.GetInt("status", mysqldb.StatusAll)
    taskId := t.GetString("task_id")
    taskOwner := t.GetString("task_owner")

    wt := &dbtask.WeaponTask{}
    sum, err := wt.SelectCount(status, taskOwner, taskId)
    if err != nil {
        logs.Warning("task list select count failed: %s", err.Error())
        data := map[string]interface{}{"total": 0, "data": []dbtask.WeaponTask{}}
        t.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeSystemErr, "select no record", data)
        t.ServeJSON()
        return
    }

    tasks, err := wt.SelectOrderByUpdate(offset, limit, status, taskOwner, taskId)
    if err != nil {
        logs.Warning("task list select failed: %s", err.Error())
        data := map[string]interface{}{"total": 0, "data": []dbtask.WeaponTask{}}
        t.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeSystemErr, "select no record", data)
        t.ServeJSON()
        return
    }

    data := map[string]interface{}{"total": sum, "data": tasks}
    t.Data["json"] = uhttp.CreateOkResponse(data)
    t.ServeJSON()
    return
}

/**
 选中任务处理的结果
 */
func (t *TaskController) Select()  {
    t.Manager()

    taskId := t.GetString("task_id", mysqldb.SelectStrAll)
    if taskId == "" {
        logs.Error(fmt.Sprintf("input weapon task id error"))
        data := map[string]interface{}{"total": 0, "data": []dbtask.WeaponTask{}}
        t.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeParamErr, "input task id error", data)
        t.ServeJSON()
        return
    }

    task := &dbtask.WeaponTask{TaskId: taskId}
    err := task.Read("task_id")
    if err != nil {
        logs.Error(fmt.Sprintf("no input task id record: %s", err.Error()))
        data := map[string]interface{}{"total": 0, "data": []dbtask.WeaponTask{}}
        t.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeParamErr, "read for task id error", data)
        t.ServeJSON()
        return
    }

    // 尝试将ok和failed的统计计数计算出来
    if task.OkCount == 0 && task.FailedCount == 0 {
        task.OkCount, task.FailedCount = fasttask.GetTaskCount(task)
        task.Update("ok_count", "failed_count")
    }

    var tasks []dbtask.WeaponTask
    tasks = append(tasks, *task)
    data := map[string]interface{}{"total": 1, "data": tasks}
    t.Data["json"] = uhttp.CreateOkResponse(data)
    t.ServeJSON()
    return
}


type TaskWeaponLogController struct {
    ctrconfig.LoginCtr
}

/**
 选中任务相关的weapon log
 */
func (t * TaskWeaponLogController) List()  {
    t.Manager()

    offset, limit := t.DealPage()

    taskID := t.GetString("task_id")                // 必填
    if taskID == "" {
        logs.Error(fmt.Sprintf("input task id error"))
        data := map[string]interface{}{"total": 0, "data": []dbdata.WeaponLog{}}
        t.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeParamErr, "input task id error.", data)
        t.ServeJSON()
        return
    }

    wormId := t.GetString("worm_id", mysqldb.SelectStrAll)
    wpId, err := t.GetInt64("weapon_id", mysqldb.SelectIntAll)
    status, err := t.GetInt("status", mysqldb.StatusAll)

    wpLog := &dbdata.WeaponLog{}
    count, err := wpLog.Count(wormId, int(wpId), taskID, status)
    if err != nil {
        logs.Error(fmt.Sprintf("weapon log count error: %s", err.Error()))
        data := map[string]interface{}{"total": 0, "data": []dbdata.WeaponLog{}}
        t.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeSystemErr, "weapon log count error.", data)
        t.ServeJSON()
        return
    }

    wpLogs, err := wpLog.Select(offset, limit, status, wormId, int(wpId), taskID)
    if err != nil {
        logs.Error(fmt.Sprintf("weapon log select error: %s", err.Error()))
        data := map[string]interface{}{"total": 0, "data": []dbdata.WeaponLog{}}
        t.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeSystemErr, "weapon log select error.", data)
        t.ServeJSON()
        return
    }

    data := map[string]interface{}{"total": count, "data": wpLogs}
    t.Data["json"] = uhttp.CreateOkResponse(data)
    t.ServeJSON()
    return
}
